
 /* 
 * Copyright 2013 Dominik Korittki, Steffen Gruschka

   Licensed under the Apache License, Version 2.0 (the "License");
   you may not use this file except in compliance with the License.
   You may obtain a copy of the License at

       http://www.apache.org/licenses/LICENSE-2.0

   Unless required by applicable law or agreed to in writing, software
   distributed under the License is distributed on an "AS IS" BASIS,
   WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
   See the License for the specific language governing permissions and
   limitations under the License.

* 
* 
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */
package beans;

import ejb.EJBManager;
import entity.Gruppen;
import entity.Nutzer;
import java.security.MessageDigest;
import java.security.NoSuchAlgorithmException;
import java.util.ArrayList;
import java.util.List;
import javax.ejb.EJB;
import javax.ejb.EJBException;
import javax.faces.application.FacesMessage;
import javax.faces.bean.ManagedBean;
import javax.faces.bean.SessionScoped;
import javax.faces.context.ExternalContext;
import javax.faces.context.FacesContext;
import javax.transaction.RollbackException;
import javax.transaction.SystemException;

/**
 * Bean für die Nutzer-anlegen Seiten.
 * Diese Bean übernimmt die Logik des Anlegens und Löschens von Login-Befugten
 * @author Dominik K.
 * @author Steffen G.
 */
@ManagedBean(name = "nutzerVerwaltung")
@SessionScoped
public class NutzerVerwaltungBean {
    /**
     * Pfad zurück zur Verwaltung
     */
    private final static String VERWALTUNG = "../index.xhtml?faces-redirect=true";
    /**
     * Nutzer Objekt, welches die Seiten zur Datenspeicherung benutzen
     */
    private Nutzer nutzer;
    /**
     * Hier steht der Wert der Checkbox von der JSF Seite, ob dieser Benutzer Schreibrechte bekommen soll
     */
    private boolean adminCheckbox;
    /**
     * Parameter für das Paging von Tabellen
     */
    private int first;
    /**
     * EJB für JPA Logik
     */
    @EJB
    private EJBManager ejbm;

    /**
     * Legt ein neues Benutzerobjekt an
     */
    public NutzerVerwaltungBean() {
        nutzer = new Nutzer();
    }
    
    
    /**
     * Liefert das first Objekt
     * @return das first Objekt
     */
    public int getFirst() {
        return this.first;
    }

    /**
     * Setzt ein neues first Objekt
     * @param first neues Objekt
     */
    public void setFirst(int first) {
        this.first = first;
    }
    
    /**
     * Liefert das nutzer Objekt
     * @return das Objekt
     */
    public Nutzer getNutzer() {
        return nutzer;
    }

    /**
     * Setzt ein neues nutzer Objekt
     * @param nutzer neues Objekt
     */
    public void setNutzer(Nutzer nutzer) {
        this.nutzer = nutzer;
    }
    
    /**
     * Liefert das isAdminCheckbox Objekt
     * @return das Objekt
     */
    public boolean isAdminCheckbox() {
        return adminCheckbox;
    }

    /**
     * Setzt ein neues adminCheckbox Objekt
     * @param adminCheckbox neues Objekt
     */
    public void setAdminCheckbox(boolean adminCheckbox) {
        this.adminCheckbox = adminCheckbox;
    }
    
    /**
     * Liest alle Nutzer aus der Datenbank und gibt diese als Liste zurück
     * @return Liste aller Mitarbeiter
     */
    public List<Nutzer> getNutzerListe() {
        try {
            return ejbm.getNutzer();
        } catch(EJBException e) {
            exceptionHandler(e);
            return new ArrayList<Nutzer>();
        }
    }
    
    /**
     * Paging Funktion zum Weiterblättern
     */
    public void weiter() {
        try {
            first = first + 5;
            if (first == ejbm.getNutzer().size()) {
                first = ejbm.getNutzer().size() - 5;
            }
        } catch(EJBException e) {
            exceptionHandler(e);
        }
    }

    /**
     * Paging Funktion zum Zurückblättern
     */
    public void zurueck() {
        first = first - 5;
        if (first <= 0) {
            first = 0;
        }
    }
    
    /**
     * Paging-Funktion um zu entscheiden ob der zurück-Link angezeigt werden soll
     * @return Link anzeigen oder nicht
     */
    public boolean zurueckVisible() {
        if (first >= 5) {
            return true;
        } else {
            return false;
        }
    }

    /**
     * Paging-Funktion um zu entscheiden ob der weiter-Link angezeigt werden soll
     * @return Link anzeigen oder nicht
     */
    public boolean weiterVisible() {
        try {
            if (ejbm.getNutzer().size() > first+5) {
                return true;
            } else {
                return false;
            }
        } catch(EJBException e) {
            exceptionHandler(e);
        }
        return false;
    }
    
    /**
     * Paging-Funktion, die die Anzahl der Seiten anzeigt
     * @return Anzahl der Seiten
     */
    public String pageCounter() {
        return Integer.toString(first / 5 + 1);
    }
    
    /**
     * Persistiert einen neuen Nutzer
     */
    public void nutzerHinzufuegen() {
        try {
            String original = nutzer.getPassword();
            MessageDigest md = MessageDigest.getInstance("MD5");
            md.update(original.getBytes());
            byte[] digest = md.digest();
            StringBuilder sb = new StringBuilder();
            for (byte b : digest) {
                //sb.append(Integer.toHexString((int) (b & 0xff)));
                String hex = Integer.toHexString(0xFF & b);
                if (hex.length() == 1) {
                    sb.append('0');
                }
                sb.append(hex);
            }
            nutzer.setPassword(sb.toString());
            Gruppen neueGruppe = new Gruppen();
            if(isAdminCheckbox()) {
                neueGruppe.setGroupID("admin");
            } else {
                neueGruppe.setGroupID("basic");
            }
            
            neueGruppe.setUsername(nutzer.getUsername());
            ejbm.persist(nutzer);
            ejbm.persist(neueGruppe);
        } catch(EJBException e) {
            exceptionHandler(e);
        } catch (NoSuchAlgorithmException e) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = 
                    new FacesMessage(FacesMessage.SEVERITY_ERROR, 
                    "Fehlender Algorithmus", 
                    "Der Algorithmus zur Passwortverschlüsselung wurde nicht gefunden");
            facesContext.addMessage(null, facesMessage);
        } finally {
            nutzer = new Nutzer();
        }
    }
    
    /**
     * Löscht den angegebenen Nutzer
     * @param actNutzer Zu löschender Benutzer
     */
    public void nutzerEntfernen(Nutzer actNutzer) {
        try {
            if(ejbm.getNutzer().size() > 1) {
                String username = actNutzer.getUsername();
                List<Gruppen> gruppenDesNutzers = ejbm.findeGruppen(username);
                for(Gruppen g : gruppenDesNutzers) {
                    ejbm.remove(g);
                }
                ejbm.remove(actNutzer);
            } else {
                FacesContext facesContext = FacesContext.getCurrentInstance();
                FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR, 
                        "Es muss mindestens ein Benutzer eingetragen sein",
                        "Es muss mindestens ein Benutzer eingetragen sein");
                facesContext.addMessage(null, facesMessage);
            }
            
        } catch(EJBException e) {
            exceptionHandler(e);
        }
    }
    
    /**
     * Prüft ob es Nutzer gibt
     * @return true falls Nutzer vorhanden sind, false falls nein
     */
    public boolean nutzerVorhanden() {
        return getNutzerListe().isEmpty();
    }
    
    /**
     * Terminiert die Session des zurzeit eingelogten Benutzers
     * @param user Aktuell eingelogger Nutzer
     * @return Link zur Verwaltungsstartseite, sichtbar ist aufgrund der
     * terminierten Session allerdings die Loginseite
     */
    public String logout(SessionNutzer user) {
        SessionNutzer.logout(user);
        return VERWALTUNG;
    }
    
    /**
     * Analysiert die EJBException und generiert Fehlernachrichten für die JSF-Seiten
     * @param e EJBException, welche von der EJB geschmissen wurde
     */
    private void exceptionHandler(EJBException e) {
        if(e.getCausedByException() instanceof SystemException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Die Datenbank ist nicht erreichbar",
                    "Konnte keine Verbindung mit der Datenbank aufbauen");
            facesContext.addMessage(null, facesMessage);
        } else if(e.getCausedByException() instanceof RollbackException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Name bereits vorhanden, bitte Anderen wählen",
                    "Es gibt bereits einen Eintrag mit diesem Namen");
            facesContext.addMessage(null, facesMessage);
        } else if(e.getCausedByException() instanceof IllegalArgumentException) {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Datenbankeintrag nicht vorhanden",
                    "Konnte den benötigten DB-Eintrag nicht finden");
            facesContext.addMessage(null, facesMessage);
        } else {
            FacesContext facesContext = FacesContext.getCurrentInstance();
            FacesMessage facesMessage = new FacesMessage(FacesMessage.SEVERITY_ERROR,
                    "Es ist ein unbekannter Fehler aufgetreten",
                    "Unbekannter Fehler aufgetreten: " + e.getMessage());
            facesContext.addMessage(null, facesMessage);
        }
    }

    
}
